home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Turnbull China Bikeride
/
Turnbull China Bikeride - Disc 2.iso
/
STUTTGART
/
LANG
/
LISP
/
XLISP
/
XLISP21S
/
sources
/
c
/
dldmem
< prev
next >
Wrap
Text File
|
1992-04-25
|
28KB
|
1,110 lines
/* dldmem - xlisp dynamic memory management routines */
/* Copyright (c) 1985, by David Michael Betz
All Rights Reserved
Permission is granted for unrestricted non-commercial use */
/* Modified memory management scheme such that array/string space is
managed here rather than using malloc/free. The advantage of this is
the array/string space gets compacted allowing better operation when
available memory is tight or virtual memory is used. XSCHEME does this,
but probably needs it more since Xscheme functions are kept as compiled
code in arrays rather than lists. */
/* When this module is used rather than xldmem (and dlimage is used rather
than xlimage) then ALLOC and EXPAND take an additional second argument
for array segment allocation size and array segments to add, respectively.
The ROOM report is changed to indicate array allocation statistics. */
#include "xlisp.h"
/* node flags */
#define MARK 0x20
#define LEFT 0x40
/* macro to compute the size of a segment */
#define segsize(n) (sizeof(SEGMENT)+((n)-1)*sizeof(struct node))
/* external variables */
extern LVAL obarray,s_gcflag,s_gchook,s_unbound,s_debugio,true;
extern LVAL xlenv,xlfenv,xldenv;
/* For vector memory management */
#define vsegsize(n) (sizeof(VSEGMENT)+((n)-1)*sizeof(LVAL))
#define btow_size(n) (((unsigned)(n)+(sizeof(LVAL)-1))/(unsigned)sizeof(LVAL))
typedef struct vsegment {
struct vsegment FAR *vs_next; /* next vector segment */
LVAL FAR *vs_free; /* next free location in this segment */
LVAL FAR *vs_top; /* top of segment (plus one) */
LVAL vs_data[1]; /* segment data */
} VSEGMENT;
VSEGMENT FAR *vsegments; /* list of vector segments */
VSEGMENT FAR *vscurrent; /* current vector segment */
int vscount; /* number of vector segments */
LVAL FAR *vfree; /* next free location in vector space */
LVAL FAR *vtop; /* top of vector space */
/* variables local to xldmem.c and xlimage.c */
SEGMENT FAR *segs, FAR *lastseg, FAR *fixseg, FAR *charseg;
int anodes,vnodes,nsegs;
long gccalls;
long nnodes,nfree,total;
long vsfree;
LVAL fnodes;
/* forward declarations */
#ifdef ANSI
void NEAR compact_vector(VSEGMENT FAR *vseg);
void NEAR compact(void);
LVAL NEAR allocvector(int type, unsigned int size);
VSEGMENT FAR* newvsegment(unsigned int n);
#ifdef JMAC
LVAL NEAR Newnode(int type);
#else
LVAL NEAR newnode(int type);
#endif
VOID NEAR mark(LVAL ptr);
VOID NEAR sweep(void);
VOID NEAR findmem(void);
int NEAR addseg(void);
int scanvmemory(unsigned int size);
#else
FORWARD VOID compact_vector();
FORWARD VSEGMENT *newvsegment();
FORWARD VOID compact();
FORWARD LVAL allocvector();
#ifdef JMAC
FORWARD LVAL Newnode();
#else
FORWARD LVAL newnode();
#endif
FORWARD VOID mark();
FORWARD VOID sweep();
FORWARD VOID findmem();
#endif
#ifdef JMAC
LVAL _nnode = NIL;
FIXTYPE _tfixed = 0;
int _tint = 0;
#define newnode(type) (((_nnode = fnodes) != NIL) ? \
((fnodes = cdr(_nnode)), \
nfree--, \
(_nnode->n_type = type), \
rplacd(_nnode,NIL), \
_nnode) \
: Newnode(type))
#endif
/* xlminit - initialize the dynamic memory module */
VOID xlminit()
{
LVAL p;
int i;
/* initialize our internal variables */
segs = lastseg = NULL;
nnodes = nfree = total = gccalls = 0L;
nsegs = 0;
anodes = NNODES;
vnodes = VSSIZE;
fnodes = NIL;
/* initialize vector space */
vsegments = vscurrent = NULL;
vscount = 0;
vfree = vtop = NULL;
/* allocate the fixnum segment */
if ((fixseg = newsegment(SFIXSIZE)) == NULL)
xlfatal("insufficient memory");
/* initialize the fixnum segment */
p = &fixseg->sg_nodes[0];
for (i = SFIXMIN; i <= SFIXMAX; ++i) {
p->n_type = FIXNUM;
p->n_fixnum = i;
++p;
}
/* allocate the character segment */
if ((charseg = newsegment(CHARSIZE)) == NULL)
xlfatal("insufficient memory");
/* initialize the character segment */
p = &charseg->sg_nodes[0];
for (i = CHARMIN; i <= CHARMAX; ++i) {
p->n_type = CHAR;
p->n_chcode = i;
++p;
}
/* initialize structures that are marked by the collector */
obarray = NULL; /* will be set to LVAL later */
xlenv = xlfenv = xldenv = NIL; /* list heads, initially NIL */
s_gcflag = s_gchook = NULL; /* will be set to lval later */
/* allocate the evaluation stack */
xlstack = xlstktop;
/* allocate the argument stack */
xlfp = xlsp = xlargstkbase;
*xlsp++ = NIL;
/* we have to make a NIL symbol before continuing */
{
LVAL FAR *vdata;
p = xlmakesym("NIL");
MEMCPY(NIL, p, sizeof(struct node)); /* we point to this! */
defconstant(NIL, NIL);
p->n_type = FREE; /* don't collect "garbage" */
vdata = p->n_vdata; /* correct ptr for compress */
*--vdata = NIL;
}
}
/* cons - construct a new cons node */
LVAL cons(x,y)
LVAL x,y;
{
LVAL nnode;
/* get a free node */
if ((nnode = fnodes) == NIL) {
xlstkcheck(2);
xlprotect(x);
xlprotect(y);
findmem();
if ((nnode = fnodes) == NIL)
xlabort("insufficient node space");
xlpopn(2);
}
/* unlink the node from the free list */
fnodes = cdr(nnode);
--nfree;
/* initialize the new node */
nnode->n_type = CONS;
rplaca(nnode,x);
rplacd(nnode,y);
/* return the new node */
return (nnode);
}
/* cvstring - convert a string to a string node */
LVAL cvstring(str)
char FAR *str;
{
LVAL val;
val = newstring(STRLEN(str));
STRCPY(getstring(val),str);
return (val);
}
/* newstring - allocate and initialize a new string */
LVAL newstring(size)
unsigned size;
{
LVAL val;
val = allocvector(STRING,btow_size(size+1));
val->n_strlen = size;
return (val);
}
/* cvsymbol - convert a string to a symbol */
LVAL cvsymbol(pname)
char *pname;
{
LVAL val;
xlsave1(val);
val = allocvector(SYMBOL,SYMSIZE);
setvalue(val,s_unbound);
setfunction(val,s_unbound);
setpname(val,cvstring(pname));
xlpop();
return (val);
}
/* cvsubr - convert a function to a subr or fsubr */
#ifdef ANSI
LVAL cvsubr(LVAL (*fcn)(void), int type, int offset)
#else
LVAL cvsubr(fcn,type,offset)
LVAL (*fcn)(); int type,offset;
#endif
{
LVAL val;
val = newnode(type);
val->n_subr = fcn;
val->n_offset = offset;
return (val);
}
/* cvfile - convert a file pointer to a stream */
LVAL cvfile(fp, iomode)
FILEP fp;
int iomode;
{
LVAL val;
val = newnode(STREAM);
setfile(val,fp);
setsavech(val,'\0');
val->n_sflags = iomode;
val->n_cpos = 0;
return (val);
}
#ifdef JMAC
/* cvfixnum - convert an integer to a fixnum node */
LVAL Cvfixnum(n)
FIXTYPE n;
{
LVAL val;
val = newnode(FIXNUM);
val->n_fixnum = n;
return (val);
}
#else
/* cvfixnum - convert an integer to a fixnum node */
LVAL cvfixnum(n)
FIXTYPE n;
{
LVAL val;
if (n >= SFIXMIN && n <= SFIXMAX)
return (&fixseg->sg_nodes[(int)n-SFIXMIN]);
val = newnode(FIXNUM);
val->n_fixnum = n;
return (val);
}
#endif
#ifdef RATIOS
/* cvratio - convert an integer pair to a ratio node */
LVAL cvratio(num, denom)
FIXTYPE num, denom;
{
LVAL val;
FIXTYPE n, m, r;
if (num == 0) return cvfixnum((FIXTYPE) 0); /* zero is int zero */
if (denom < 0) { /* denominator must be positive */
denom = -denom;
num = -num;
}
if ((n = num) < 0) n = -n;
m = denom; /* reduce the ratio: compute GCD */
for (;;) {
if ((r = m % n) == 0) break;
m = n;
n = r;
}
if (n != 1) {
denom /= n;
num /= n;
}
if (denom == 1) return cvfixnum(num); /* reduced to integer */
val = newnode(RATIO);
val->n_denom = denom;
val->n_numer = num;
return (val);
}
#endif
/* cvflonum - convert a floating point number to a flonum node */
LVAL cvflonum(n)
FLOTYPE n;
{
LVAL val;
val = newnode(FLONUM);
val->n_flonum = n;
return (val);
}
/* cvchar - convert an integer to a character node */
#ifdef JMAC
LVAL Cvchar(n)
int n;
{
xlerror("character code out of range",cvfixnum((FIXTYPE)n));
return (NIL); /* never really returns */
}
#else
LVAL cvchar(n)
int n;
{
#if (CHARMIN == 0) /* TAA MOD eliminating a comparison */
if (((unsigned)n) <= CHARMAX)
#else
if (n >= CHARMIN && n <= CHARMAX)
#endif
return (&charseg->sg_nodes[n-CHARMIN]);
xlerror("character code out of range",cvfixnum((FIXTYPE)n));
return (NIL); /* never really returns */
}
#endif
/* newustream - create a new unnamed stream */
LVAL newustream()
{
LVAL val;
val = newnode(USTREAM);
sethead(val,NIL);
settail(val,NIL);
return (val);
}
/* newobject - allocate and initialize a new object */
LVAL newobject(cls,size)
LVAL cls; int size;
{
LVAL val;
val = allocvector(OBJECT,size+1);
setelement(val,0,cls);
return (val);
}
/* newclosure - allocate and initialize a new closure */
LVAL newclosure(name,type,env,fenv)
LVAL name,type,env,fenv;
{
LVAL val;
val = allocvector(CLOSURE,CLOSIZE);
setname(val,name);
settype(val,type);
setenvi(val,env);
setfenv(val,fenv);
return (val);
}
/* newstruct - allocate and initialize a new structure node */
LVAL newstruct(type,size)
LVAL type; int size;
{
LVAL val;
val = allocvector(STRUCT,size+1);
setelement(val,0,type);
return (val);
}
/* newvector - allocate and initialize a new vector */
LVAL newvector(size)
unsigned size;
{
return (allocvector(VECTOR,size));
}
/* getvused - get used vector space */
/* also sets vsfree to free space */
#ifdef ANSI
static long NEAR getvused(void)
#else
LOCAL long getvused()
#endif
{
long vnu=0L;
VSEGMENT FAR *vseg;
vsfree = 0L;
if (vscurrent != NULL)
vscurrent->vs_free = vfree;
for (vseg = vsegments; vseg != NULL; vseg = vseg->vs_next) {
vnu += ((long)vseg->vs_free - (long)&vseg->vs_data[0])/sizeof(LVAL FAR *);
vsfree += ((long)vseg->vs_top - (long)vseg->vs_free)/sizeof(LVAL FAR *);
}
return vnu;
}
/* allocvector - allocate and initialize a new vector node */
LOCAL LVAL NEAR allocvector(type,size)
int type;
unsigned size;
{
LVAL val, FAR *p;
unsigned int i;
if (size+1 > MAXVLEN) xlfail("array too large");
xlsave1(val);
val = newnode(type);
/* initialize the vector node */
val->n_type = type;
val->n_vsize = size;
val->n_vdata = NULL;
/* add space for the backpointer */
++size;
/* make sure there's enough space */
if (((unsigned)vtop-(unsigned)vfree < size*sizeof(LVAL FAR *)) &&
!scanvmemory(size)) {
gc(); /* try cleaning up and scanning again */
getvused(); /* calculate free and used space */
if (!scanvmemory(size) || vsfree < vnodes)
newvsegment(size); /* no memory -- allocate segment */
if ((unsigned)vtop-(unsigned)vfree < size*sizeof(LVAL FAR *))
xlabort("insufficient vector space");
}
/* allocate the next available block */
p = vfree;
vfree += size;
/* store the backpointer */
*p++ = val;
val->n_vdata = p;
/* set all the elements to NIL, except for STRINGs */
if (type != STRING) for (i = size; i > 1; --i) *p++ = NIL;
/* return the new vector */
xlpop();
return (val);
}
/* scanvmemory - look for vector segment with enough space */
/* return success */
int scanvmemory(size)
unsigned int size;
{
VSEGMENT FAR *vseg;
if (vscurrent != NULL)
vscurrent->vs_free = vfree;
for (vseg = vsegments; vseg != NULL; vseg = vseg->vs_next)
if ((unsigned)vseg->vs_top - (unsigned)vseg->vs_free >
size*sizeof(LVAL FAR *)) {
vfree = vseg->vs_free;
vtop = vseg->vs_top;
vscurrent = vseg;
return TRUE;
}
return FALSE;
}
/* newvsegment - create a new vector segment */
VSEGMENT FAR *newvsegment(n)
unsigned int n;
{
VSEGMENT FAR *newseg;
long reqsize;
if (n < vnodes) n = vnodes; /* allocate vnodes if larger than request */
reqsize = vsegsize((long)n);
if ((unsigned int)reqsize != reqsize) return NULL; /* can't do it */
/* allocate the new segment */
if ((newseg = (VSEGMENT FAR *)MALLOC((unsigned int)reqsize)) == NULL)
return (NULL);
if (vscurrent != NULL)
vscurrent->vs_free = vfree;
/* initialize the new segment */
vfree = newseg->vs_free = &newseg->vs_data[0];
vtop = newseg->vs_top = newseg->vs_free + n;
newseg->vs_next = vsegments;
vscurrent = vsegments = newseg;
/* update the statistics */
total += reqsize;
++vscount;
/* return the new segment */
return (newseg);
}
/* newnode - allocate a new node */
#ifdef JMAC
LOCAL LVAL NEAR Newnode(type)
int type;
{
LVAL nnode;
/* get a free node */
findmem();
if ((nnode = fnodes) == NIL)
xlabort("insufficient node space");
/* unlink the node from the free list */
fnodes = cdr(nnode);
nfree -= 1L;
/* initialize the new node */
nnode->n_type = type;
rplacd(nnode,NIL);
/* return the new node */
return (nnode);
}
#else
LOCAL LVAL NEAR newnode(type)
int type;
{
LVAL nnode;
/* get a free node */
if ((nnode = fnodes) == NIL) {
findmem();
if ((nnode = fnodes) == NIL)
xlabort("insufficient node space");
}
/* unlink the node from the free list */
fnodes = cdr(nnode);
nfree -= 1L;
/* initialize the new node */
nnode->n_type = type;
rplacd(nnode,NIL);
/* return the new node */
return (nnode);
}
#endif
/* findmem - find more memory by collecting then expanding */
LOCAL VOID NEAR findmem()
{
gc();
if (nfree < (long)anodes)
addseg();
}
/* gc - garbage collect (only called here and in xlimage.c) */
VOID gc()
{
LVAL **p,*ap,tmp;
FRAMEP newfp;
LVAL fun;
/* print the start of the gc message */
if (s_gcflag!=NULL && getvalue(s_gcflag) != NIL) {
/* print message on a fresh line */
xlfreshline(getvalue(s_debugio));
sprintf(buf,"[ gc: total %ld, ",nnodes);
dbgputstr(buf); /* TAA MOD -- was std output */
}
/* mark the obarray, the argument list and the current environment */
if (obarray != NULL)
mark(obarray);
if (xlenv != NIL)
mark(xlenv);
if (xlfenv != NIL)
mark(xlfenv);
if (xldenv != NIL)
mark(xldenv);
mark(NIL);
/* mark the evaluation stack */
for (p = xlstack; p < xlstktop; ++p)
if ((tmp = **p) != NIL)
mark(tmp);
/* mark the argument stack */
for (ap = xlargstkbase; ap < xlsp; ++ap)
if ((tmp = *ap) != NIL)
mark(tmp);
/* compact vector space */
compact();
/* sweep memory collecting all unmarked nodes */
sweep();
NIL->n_type &= ~MARK;
/* count the gc call */
++gccalls;
/* call the *gc-hook* if necessary */
if (s_gchook != NULL && ((fun = getvalue(s_gchook)) != NIL) ) {
/* rebind hook function to NIL TAA MOD */
tmp = xldenv;
xldbind(s_gchook,NIL);
newfp = xlsp;
pusharg(cvfixnum((FIXTYPE)(newfp - xlfp)));
pusharg(fun);
pusharg(cvfixnum((FIXTYPE)2));
pusharg(cvfixnum((FIXTYPE)nnodes));
pusharg(cvfixnum((FIXTYPE)nfree));
xlfp = newfp;
xlapply(2);
/* unbind the symbol TAA MOD */
xlunbind(tmp);
}
/* print the end of the gc message */
if (s_gcflag != NULL && getvalue(s_gcflag) != NIL) {
sprintf(buf,"%ld free ]\n",nfree);
dbgputstr(buf); /* TAA MOD -- was std output */
}
}
/* mark - mark all accessible nodes */
LOCAL VOID NEAR mark(ptr)
LVAL ptr;
{
register LVAL this,prev,tmp;
int i,n;
/* initialize */
prev = NIL;
this = ptr;
/* mark this list */
for (;;) {
/* descend as far as we can */
while (!(this->n_type & MARK))
/* check cons and unnamed stream nodes */
if (((i = (this->n_type |= MARK) & TYPEFIELD) == CONS)||
(i == USTREAM)) {
if ((tmp = car(this)) != NIL) {
this->n_type |= LEFT;
rplaca(this,prev);
}
else if ((tmp = cdr(this)) != NIL)
rplacd(this,prev);
else /* both sides nil */
break;
prev = this; /* step down the branch */
this = tmp;
}
else {
if (((i & ARRAY) != 0) && (this->n_vdata != NULL))
for (i = 0, n = getsize(this); i < n;)
if ((tmp = getelement(this,i++)) != NIL)
if ((tmp->n_type & (ARRAY|MARK)) == ARRAY ||
tmp->n_type == CONS ||
tmp->n_type == USTREAM)
mark(tmp);
else tmp->n_type |= MARK;
break;
}
/* backup to a point where we can continue descending */
for (;;)
/* make sure there is a previous node */
if (prev!=NIL) {
if (prev->n_type & LEFT) { /* came from left side */
prev->n_type &= ~LEFT;
tmp = car(prev);
rplaca(prev,this);
if ((this = cdr(prev)) != NIL) {
rplacd(prev,tmp);
break;
}
}
else { /* came from right side */
tmp = cdr(prev);
rplacd(prev,this);
}
this = prev; /* step back up the branch */
prev = tmp;
}
/* no previous node, must be done */
else
return;
}
}
/* compact - compact vector space */
LOCAL VOID NEAR compact()
{
VSEGMENT FAR *vseg, FAR *vsold;
/* store the current segment information */
if (vscurrent != NULL)
vscurrent->vs_free = vfree;
/* compact each vector segment */
for (vseg = vsegments, vsold = (VSEGMENT FAR *)&vsegments;
vseg != NULL;
vsold = vseg, vseg = vseg->vs_next) {
compact_vector(vseg);
#if 0
if (vseg->vs_free == &vseg->vs_data[0]) { /* empty segment */
vsold->vs_next = vseg->vs_next; /* unlink segment */
vscount--; /* adjust tallies */
total -= sizeof(VSEGMENT)-sizeof(LVAL FAR *)+
(unsigned)vseg->vs_top - (unsigned)vseg->vs_free;
MFREE(vseg); /* free segment */
vseg = vsold; /* last becomes current */
}
#endif
}
/* make the first vector segment current */
if ((vscurrent = vsegments) != NULL) {
vfree = vscurrent->vs_free;
vtop = vscurrent->vs_top;
}
getvused(); /* calculate free and used space */
/* and free any unused segments if lots of free space (TAA MOD) */
if (vsfree > 2*(long)vnodes) {
for (vseg = vsegments, vsold = (VSEGMENT FAR *)&vsegments;
vseg != NULL;
vsold = vseg, vseg = vseg->vs_next)
if (vseg->vs_free == &vseg->vs_data[0]) { /* empty segment */
vsold->vs_next = vseg->vs_next; /* unlink segment */
vscount--; /* adjust tallies */
total -= sizeof(VSEGMENT)-sizeof(LVAL FAR *)+
(unsigned)vseg->vs_top - (unsigned)vseg->vs_free;
MFREE(vseg); /* free segment */
vseg = vsold; /* last becomes current */
}
/* make the first vector segment current */
if ((vscurrent = vsegments) != NULL) {
vfree = vscurrent->vs_free;
vtop = vscurrent->vs_top;
}
}
}
/* compact_vector - compact a vector segment */
LOCAL VOID NEAR compact_vector(vseg)
VSEGMENT FAR *vseg;
{
LVAL FAR *vdata, FAR *vnext, FAR *vfree,vector;
unsigned vsize;
vdata = vnext = &vseg->vs_data[0];
vfree = vseg->vs_free;
while (vdata < vfree) {
vector = *vdata;
if ((vector->n_type & TYPEFIELD) == STRING)
vsize = btow_size(vector->n_strlen+1) + 1;
else
vsize = vector->n_vsize + 1;
if (vector->n_type & MARK) {
if (vdata != vnext) {
vector->n_vdata = vnext + 1;
MEMCPY(vnext, vdata, vsize * (unsigned)sizeof(LVAL));
}
vnext += vsize;
}
vdata += vsize;
}
vseg->vs_free = vnext;
}
/* sweep - sweep all unmarked nodes and add them to the free list */
LOCAL VOID NEAR sweep()
{
SEGMENT FAR *seg;
LVAL p;
int n;
/* empty the free list */
fnodes = NIL;
nfree = 0L;
/* add all unmarked nodes */
for (seg = segs; seg != NULL; seg = seg->sg_next) {
if (seg == fixseg || seg == charseg) {
/* remove marks from segments */
p = &seg->sg_nodes[0];
for (n = seg->sg_size; --n >= 0;)
(p++)->n_type &= ~MARK;
continue;
}
p = &seg->sg_nodes[0];
for (n = seg->sg_size; --n >= 0;)
if (p->n_type & MARK)
(p++)->n_type &= ~MARK;
else {
if (((ntype(p)&TYPEFIELD) == STREAM)
&& getfile(p) != CLOSED
&& getfile(p) != STDIN
&& getfile(p) != STDOUT
&& getfile(p) != CONSOLE)/* taa fix - dont close stdio */
OSCLOSE(getfile(p));
p->n_type = FREE;
rplaca(p,NIL);
rplacd(p,fnodes);
fnodes = p++;
nfree++;
}
}
}
/* addseg - add a segment to the available memory */
LOCAL int NEAR addseg()
{
SEGMENT FAR *newseg;
LVAL p;
int n;
/* allocate the new segment */
if (anodes == 0 || (newseg = newsegment(anodes)) == NULL)
return (FALSE);
/* add each new node to the free list */
p = &newseg->sg_nodes[0];
for (n = anodes; --n >= 0; ++p) {
rplacd(p,fnodes);
fnodes = p;
}
/* return successfully */
return (TRUE);
}
/* newsegment - create a new segment (only called here and in xlimage.c) */
SEGMENT FAR *newsegment(n)
int n;
{
SEGMENT FAR *newseg;
/* allocate the new segment */
if ((newseg = (SEGMENT FAR *)CALLOC(1,segsize(n))) == NULL)
return (NULL);
/* initialize the new segment */
newseg->sg_size = n;
newseg->sg_next = NULL;
if (segs != NULL)
lastseg->sg_next = newseg;
else
segs = newseg;
lastseg = newseg;
/* update the statistics */
total += (long)segsize(n);
nnodes += (long)n;
nfree += (long)n;
++nsegs;
/* return the new segment */
return (newseg);
}
/* stats - print memory statistics */
#ifdef ANSI
static void NEAR stats(void)
#else
LOCAL VOID stats()
#endif
{
sprintf(buf,"Nodes: %ld\n",nnodes); stdputstr(buf);
sprintf(buf,"Free nodes: %ld\n",nfree); stdputstr(buf);
sprintf(buf,"Segments: %d\n",nsegs); stdputstr(buf);
sprintf(buf,"Vector nodes: %ld\n",getvused()); stdputstr(buf);
sprintf(buf,"Vector free: %ld\n",vsfree); stdputstr(buf);
sprintf(buf,"Vector segs: %d\n",vscount); stdputstr(buf);
sprintf(buf,"Allocate: %d\n",anodes); stdputstr(buf);
sprintf(buf,"Vec Allocate: %d\n",vnodes); stdputstr(buf);
sprintf(buf,"Total: %ld\n",total); stdputstr(buf);
sprintf(buf,"Collections: %ld\n",gccalls); stdputstr(buf);
}
/* xgc - xlisp function to force garbage collection */
LVAL xgc()
{
/* make sure there aren't any arguments */
xllastarg();
/* garbage collect */
gc();
/* return nil */
return (NIL);
}
/* xexpand - xlisp function to force memory expansion */
LVAL xexpand()
{
LVAL num;
FIXTYPE n,i;
/* get the new number to allocate */
if (moreargs()) {
num = xlgafixnum();
n = getfixnum(num);
xllastarg();
}
else
n = 1;
/* allocate more segments */
for (i = 0; i < n; i++)
if (!addseg())
break;
/* return the number of segments added */
return (cvfixnum((FIXTYPE)i));
}
/* xalloc - xlisp function to set the number of nodes to allocate */
LVAL xalloc()
{
FIXTYPE n,vn; /* TAA MOD -- prevent overflow */
int oldn;
/* get the new number to allocate */
n = getfixnum(xlgafixnum());
if (moreargs()) { /* vector allocation */
vn = getfixnum(xlgafixnum());
xllastarg();
/* clip to reasonable values*/
if (vn > (long)MAXVLEN-sizeof(VSEGMENT)/sizeof(LVAL))
vn = MAXVLEN-sizeof(VSEGMENT)/sizeof(LVAL);
else if (vn < 1000) vn = 1000;
vnodes = (int)vn;
}
/* Place limits on argument by clipping to reasonable values TAA MOD */
if (n > ((long)MAXSLEN - sizeof(SEGMENT))/sizeof(struct node))
n = ((long)MAXSLEN - sizeof(SEGMENT))/sizeof(struct node);
else if (n < 1000)
n = 1000; /* arbitrary */
/* set the new number of nodes to allocate */
oldn = anodes;
anodes = (int)n;
/* return the old number */
return (cvfixnum((FIXTYPE)oldn));
}
/* xmem - xlisp function to print memory statistics */
LVAL xmem()
{
/* allow one argument for compatiblity with common lisp */
if (xlargc > 1) xltoomany(); /* TAA Mod */
/* print the statistics */
stats();
/* return nil */
return (NIL);
}
#ifdef SAVERESTORE
/* xsave - save the memory image */
LVAL xsave()
{
#ifdef MEDMEM
char name[STRMAX];
#else
char *name;
#endif
/* get the file name */
#ifdef MEDMEM
_fstrncpy(name, getstring(xlgetfname()), STRMAX);
name[STRMAX-1] = '\0';
#else
name = getstring(xlgetfname());
#endif
xllastarg();
/* save the memory image */
return (xlisave(name) ? true : NIL);
}
/* xrestore - restore a saved memory image */
LVAL xrestore()
{
extern jmp_buf top_level;
#ifdef MEDMEM
char name[STRMAX];
#else
char *name;
#endif
/* get the file name */
#ifdef MEDMEM
_fstrncpy(name, getstring(xlgetfname()), STRMAX);
name[STRMAX-1] = '\0';
#else
name = getstring(xlgetfname());
#endif
xllastarg();
/* restore the saved memory image */
if (!xlirestore(name))
return (NIL);
/* return directly to the top level */
dbgputstr("[ returning to the top level ]\n"); /* TAA MOD --was std out*/
longjmp(top_level,1);
return (NIL); /* never executed, but avoids warning message */
}
#endif
#ifdef COMPLX
/* From XLISP-STAT, Copyright (c) 1988 Luke Tierney */
LVAL newicomplex(real, imag)
FIXTYPE real, imag;
{
LVAL val;
if (imag == 0) val = cvfixnum(real);
else {
xlsave1(val);
val = newvector(2);
val->n_type = COMPLEX;
setelement(val, 0, cvfixnum(real));
setelement(val, 1, cvfixnum(imag));
xlpop();
}
return(val);
}
LVAL newdcomplex(real, imag)
double real, imag;
{
LVAL val;
xlsave1(val);
val = newvector(2);
val->n_type = COMPLEX;
setelement(val, 0, cvflonum((FLOTYPE) real));
setelement(val, 1, cvflonum((FLOTYPE) imag));
xlpop();
return(val);
}
/* newcomplex - allocate and initialize a new object */
LVAL newcomplex(real,imag)
LVAL real,imag;
{
if (fixp(real) && fixp(imag))
return(newicomplex(getfixnum(real), getfixnum(imag)));
else
return(newdcomplex(makefloat(real), makefloat(imag)));
}
#endif